#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "monitor.h"
#include "house.h"

void iniciaMonitor(Monitor *m)
{
	pthread_mutex_init(&m->mutex, NULL);
	pthread_cond_init(&m->fornoOcupado, NULL);
	m->numPesonagemUsandoForno = 0;
	fimUsoDoForno = 0;
}

//Raj
void iniciaMediador(Monitor *m, Personagem *mediador)
{
	mediador->m = m;
	mediador->num_cliente = 6;
}

//http://www.inf.ufes.br/~zegonc/material/Sistemas%20Operacionais/SO%20old/S.O/Apostilas%20e%20Livros/Apostila%20pthreads_em_C%20Guilherme.pdf
void personagens(Personagem *personagem)
{
	//QUANTIDADE QUE CADA PERSONAGEM UTILIZA O FORNO - 3 vezes - PROVISÓRIO

	//Enquanto cada personagem não termina sua quota de utilização do forno passado como argumento no programa.
	while(personagem->quantidadeUsoForno < 3)
	{
		querUsarForno(personagem);
	}
	pthread_mutex_lock(&personagem->m->mutex);
	fimUsoDoForno++;
	pthread_mutex_unlock(&personagem->m->mutex);
	pthread_exit(NULL);
}

void criaMediador(Personagem *mediador)
{
	//Enquanto todos os usuários não terminaram de usar o forno.
	while(fimUsoDoForno < NUM_MAX_REQUERENTES_FORNO)
	{
		pthread_mutex_lock(&mediador->m->mutex);
		escalonarFilaUsoForno(mediador);
		//printf("\tESCALONADO\n");
		pthread_mutex_unlock(&mediador->m->mutex);
		//sleep(1);
	}
	pthread_exit(NULL);
}

void escalonarFilaUsoForno(Personagem *mediador)
{
	ordenaPelaQuantidadeDeUso();
	ordenaPelaPrioridade();
}

void ordenaPelaPrioridade()
{
	int aux;
	int j, i;
	int tamanho = tamanhoDaFila();
	for(i = 0; i < tamanho - 1; i++)
	{
		for(j=i+1; j < tamanho ; j++)
		{
			if(fila[i] > fila[j])
			{
				aux = fila[i];
				fila[i] = fila[j];
				fila[j] = aux;
			}
		}
	}
}

void ordenaPelaQuantidadeDeUso()
{

}

int tamanhoDaFila()
{
	int contador = 0;
	while(fila[contador] != -1)
	{
		contador++;
	}
	return contador;
}

void querUsarForno(Personagem *personagem)
{
	printf("%s quer usar o forno\n", qualPersonagem(personagem->num_cliente));
	esperar();
	pthread_mutex_lock(&personagem->m->mutex);
	adicionaFila(personagem->num_cliente);
	pthread_mutex_unlock(&personagem->m->mutex);
	forno(personagem);
}

void forno(Personagem *personagem)
{
	int condicao = TRUE;
	while(condicao)
	{
		pthread_mutex_lock(&personagem->m->mutex);
		if(fila[0] != personagem->num_cliente) pthread_cond_wait(&personagem->m->fornoOcupado, &personagem->m->mutex);
		pthread_cond_signal(&personagem->m->fornoOcupado);
		condicao = FALSE;
		removePrimeiroDaFila();
		printf("%s Começa a usar o forno\n", qualPersonagem(personagem->num_cliente));
		personagem->quantidadeUsoForno++;
		esperar();
		printf("%s vai comer\n", qualPersonagem(personagem->num_cliente));
		pthread_mutex_unlock(&personagem->m->mutex);
		esperar();
	}
}

void esperar()
{
	double aleatorio = drand48();
	int i;
	for(i = 0; i < 100000000*aleatorio; i++) ; //esperar algo
}

char *qualPersonagem(int numero)
{
	int i;
	for(i = 0; i < NUM_MAX_REQUERENTES_FORNO; i++)
	{
		if(dados[i].numero == numero)
		{
			return dados[i].nome;
		}
	}
	return "";
}
